<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // class Person{
        //     constructor(name){
        //         this.name = name
        //     }
        // }

        // let instance = null;


        // function singleton(name){
        //     if(!instance){
        //         // 如果进来说明没有实例化过对象
        //         instance = new Person(name)
        //     }

        //     return instance;

        // }

        // const p1 = singleton('张三');
        // const p2 = singleton('李四');
        // const p3 = singleton('王五');
        // console.log(p1.name);
        // console.log(p2.name);
        // console.log(p3.name);


        // 解决向外暴漏了一个变量的问题 
        // class Person{
        //     constructor(name){
        //         this.name = name
        //     }


        // }


        // const singleton = (function(){
        //     let instance = null;


        //     return function inner(name){
        //         if(!instance){
        //             // 如果进来说明没有实例化过对象
        //             instance = new Person(name)
        //         }

        //         return instance;

        //     }
        // })();

        // console.log(singleton('张三')); // 张三
        // console.log(singleton('李四')); // 张三
        // console.log(singleton('王五')); // 张三

        // 现在 我们把instance变成了一个私有变量  全局不可能随便使用了 

        // 还有一个问题 多次传递参数 起不到改变效果  传李四 传王五都没用 

        // 解决方案  
        // class Person{
        //     constructor(){
        //         this.name = '';  //只执行一次  new Person()执行一次 
        //     }

        //     init(str){   // 每次实例化都会执行  
        //         this.name = str
        //     }
        // }


        // const singleton = (function(){
        //     let instance = null;


        //     return function inner(name){
        //         if(!instance){
        //             // 如果进来说明没有实例化过对象
        //             instance = new Person(); // 实例化的对象 
        //             // 这里边代码仅仅执行一次  张三是第一次 所以只有
        //             // 张三进来了  
        //         }
        //         instance.init(name); // 这段代码每次都会执行 

        //         return instance;

        //     }
        // })();

        // /console.log(singleton('张三').name); // 张三

        // 第一次  instance = null; ,然后 singleton('张三')
        // inner(张三)执行  
        // 进到 if 
        // 实例化对象   这时候name 是空字符串 
        // instance 变成了  创建的对象 name属性空的 

        //  instance.init(张三); instance的name 变成张三 

        // console.log(singleton('李四').name); // 李四
        // 第二次  instance 是一个nam为张三的对象 ; ,然后 singleton('李四')
        // inner(李四)执行  
        // 不进if   instance还是上次创建的对象 
        //  instance.init(李四); instance的name 变成李四 
        // console.log(singleton('王五').name); // 王五

        // 第二次  instance 是一个name为李四的对象 ; ,然后 singleton('王五')
        // inner(王五)执行  
        // 不进if   instance还是上次创建的对象 
        //  instance.init(王五); instance的name 变成王五


        // 上面解决了  instance 暴露 传递消息不起作用  
        // 但是问题是  完全可以绕开Singleton去实例化对象 

        // class Person{
        //     constructor(){
        //         this.name = '';  //只执行一次  new Person()执行一次 
        //     }

        //     init(str){   // 每次实例化都会执行  
        //         this.name = str
        //     }
        // }
        // const singleton = (function(){

        // })();

        // 完全可以  new Person().init('张三')
        // 完全可以  new Person().init('李四')
        // 完全可以  new Person().init('王五')
        // 完全可以  new Person().init('赵六')
        // 上面绕开了 singleton 创了四个实例  
        // 单例模式完全没有作用了  


        // 解决方案: 

        // 把类也放到  singleton中 ,这下实例化对象 必须走singleton
        // 只要确保走singleton  到最后一定只是实例化了一个对象   




        //  const singleton = (function () {
        //     class Person {
        //         constructor() {
        //             this.name = '';  //只执行一次  new Person()执行一次 
        //         }

        //         init(str) {   // 每次实例化都会执行  
        //             this.name = str
        //         }
        //     }

        //     let instance = null;
        //     return function inner(...arg){
        //         if(!instance){
        //             instance =new Person()
        //         }

        //         instance.init(...arg)

        //         return instance
        //     }
        // })();

        

        // const p1 = singleton('zhangsan');
        // console.log(p1);
        // const p2 = singleton('lisi');
        // console.log(p2);
        // const p3 = singleton('wangwu');
        // console.log(p3);

        // 上面必须走singleton 


        // 用户习惯 new 实例化一个对象  
        // 把singleton名字改成  Person 

        // 外边的Person 的inner函数  因为名字第一个字母大写 构造函数
        
        // person 得到 一个 函数  inner
 const Person = (function () {
            class Person {
                constructor() {
                    this.name = '';  //只执行一次  new Person()执行一次 
                }

                init(str) {   // 每次实例化都会执行  
                    this.name = str
                }
            }

            let instance = null;
            return function inner(...arg){
                if(!instance){
                    instance =new Person()
                }

                instance.init(...arg)

                return instance
            }
        })();


        const p1  = new Person('张三');// inner('张三')
        console.log(p1);

        const p2  = new Person('李四');
        console.log(p2);

        const p3  = new Person('王五');
        console.log(p3);
        


        // 外界看起来是张三 李四 王五  
        // 实际上这三个是同一个对象 

        console.log(p1 === p2);
        console.log(p2 === p3);
        console.log(p1 === p3);







    </script>
</body>

</html>